home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / console / svgatext.3 / svgatext / SVGATextMode-1.3 / XFREE / common_hw / I2061Aalt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-19  |  6.6 KB  |  314 lines

  1. /* $XConsortium: I2061Aalt.c,v 1.1 95/01/26 15:25:49 kaleb Exp $ */
  2. /* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/I2061Aalt.c,v 3.5 1995/07/01 10:48:58 dawes Exp $ */
  3.  
  4. /*
  5.  * This code is derived from code available from the STB bulletin board
  6.  */
  7.  
  8. #include "compiler.h"
  9.  
  10. #define SEQREG   0x03C4
  11. #define MISCREG  0x03C2
  12. #define MISCREAD 0x03CC
  13.  
  14. double fref = 14.31818 * 2.0;
  15. char ascclk[] = "VIDEO CLOCK ?";
  16.  
  17. unsigned short clknum;
  18. unsigned short vlbus_flag;
  19. unsigned short card;
  20. unsigned short crtcaddr;
  21. unsigned short clockreg;
  22.  
  23. static double range[15] = {50.0, 51.0, 53.2, 58.5, 60.7, 64.4, 66.8, 73.5, 
  24.                75.6, 80.9, 83.2, 91.5, 100.0, 120.0, 120.0000001};
  25.  
  26. #if NeedFunctionPrototypes
  27. #if 0
  28. static void prtbinary(unsigned int size, unsigned int val);
  29. #endif
  30. static void wait_vb();
  31. static void wrt_clk_bit(unsigned int value);
  32. static void s3_init_clock(unsigned long setup,  unsigned short crtcport);
  33. static void et4000_init_clock(unsigned long setup);
  34. #else
  35. #if 0
  36. static void prtbinary();
  37. #endif
  38. static void wait_vb();
  39. static void wrt_clk_bit();
  40. static void s3_init_clock();
  41. #endif
  42.  
  43. static unsigned long AltICD2061CalcClock(frequency, select)
  44. register long   frequency;               /* in Hz */
  45. int select;
  46. {
  47.    unsigned int m;
  48.    int i;
  49.    long dwv;
  50.    double realval;
  51.    double freq, fvco;
  52.    double dev, devx;
  53.    double delta, deltax;
  54.    double f0;
  55.    unsigned int p, q;
  56.    unsigned int bestp=0, bestq=0, bestm=0, besti=0;
  57.  
  58.    clknum = select;
  59.  
  60.    freq = ((double)frequency)/1000000.0;
  61.    if (freq > range[13])
  62.       freq = range[13];
  63.    else if (freq < 7.0)
  64.       freq = 7.0;
  65.  
  66. /*
  67.  *  Calculate values to load into ICD 2061A clock chip to set frequency
  68.  */
  69.    delta = 999.0;
  70.    dev   = 999.0;
  71.  
  72.    for (m = 0; m < 8; m++) {
  73.       fvco = freq * (1<<m);
  74.       if (fvco < 50.0 || fvco > 120.0) continue;
  75.       
  76.       f0  = fvco / fref;
  77.  
  78.       for (q = 14; q <= 71; q++) {     /* q={15..71}:Constraint 2 on page 14 */
  79.      p = (int)(f0 * q + 0.5);
  80.      if (p < 4 || p > 130)      /* p={4..130}:Constraint 5 on page 14 */
  81.         continue; 
  82.      deltax = (double)(p) / (double)(q) - f0;
  83.      if (deltax < 0) deltax = -deltax;
  84.      if (deltax <= delta) {
  85.         for (i = 13; i >= 0; i--)
  86.            if (fvco >= range[i])
  87.           break;
  88.         devx = (fvco - (range[i] + range[i+1])/2)/fvco;
  89.         if (devx < 0)
  90.            devx = -devx;
  91.         if (deltax < delta || devx < dev) {
  92.            delta = deltax;
  93.            dev   = devx;
  94.            bestp = p;
  95.            bestq = q;
  96.            bestm = m;
  97.            besti = i;
  98.         }
  99.      }
  100.       }
  101.    }
  102.    fvco = fref / (1<<bestm);
  103.    realval = (fvco * bestp) /  bestq;
  104.    dwv = ((((((long)besti << 7) | (bestp-3)) << 3) | bestm) << 7) | (bestq-2);
  105.  
  106. #if 0
  107.    fprintf(stderr, "I2061Aalt.c: freq %ld, clknum %d\n", (((4*14318lu*bestp/bestq)>>bestm)+1)>>1,
  108.        clknum);
  109. #endif
  110.    return (((unsigned long)dwv) | (((long)clknum) << 21));
  111. }
  112.  
  113.  
  114. void AltICD2061SetClock(frequency, select)
  115. register long   frequency;               /* in Hz */
  116. int select;
  117. {
  118.    unsigned char tmp;
  119.  
  120.    crtcaddr=(inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
  121.  
  122.    outb(crtcaddr, 0x11);    /* Unlock CRTC registers */
  123.    tmp = inb(crtcaddr + 1);
  124.    outb(crtcaddr + 1, tmp & ~0x80);
  125.  
  126.    outw(crtcaddr, 0x4838);    /* Unlock S3 register set */
  127.    outw(crtcaddr, 0xA039);
  128.    /* Write ICD 2061A clock chip */
  129.    s3_init_clock(AltICD2061CalcClock(frequency, select), crtcaddr);
  130.  
  131.    wait_vb();
  132.    wait_vb();
  133.    wait_vb();
  134.    wait_vb();
  135.    wait_vb();
  136.    wait_vb();
  137.    wait_vb();        /* 0.10 second delay... */
  138. }
  139.  
  140. void Et4000AltICD2061SetClock(frequency, select)
  141. register long   frequency;               /* in Hz */
  142. int select;
  143. {
  144.    crtcaddr=(inb(0x3CC) & 0x01) ? 0x3D4 : 0x3B4;
  145.  
  146.    /* Write ICD 2061A clock chip */
  147.    et4000_init_clock(AltICD2061CalcClock(frequency, select));
  148.    
  149.    /* select the clock */
  150.    outb(0x3C2,(inb(0x3CC) & 0xF3) | ((select << 2) & 0x0C));
  151.  
  152.    wait_vb();
  153.    wait_vb();
  154.    wait_vb();
  155.    wait_vb();
  156.    wait_vb();
  157.    wait_vb();
  158.    wait_vb();        /* 0.10 second delay... */
  159. }
  160.  
  161.  
  162. #if 0
  163. static void prtbinary(size, val)
  164.    unsigned int size;
  165.    unsigned int val;
  166.    {
  167.    unsigned int mask;
  168.    int k;
  169.  
  170.    mask = 1;
  171.  
  172.    for (k=size; --k > 0 || mask <= val/2;)
  173.       mask <<= 1;
  174.  
  175.    while (mask) {
  176.       fputc((mask&val)? '1': '0' , stderr);
  177.       mask >>= 1;
  178.       }
  179.    }
  180. #endif
  181.  
  182. static void wait_vb()
  183.    {
  184.    while ((inb(crtcaddr+6) & 0x08) == 0)
  185.       ;
  186.    while (inb(crtcaddr+6) & 0x08)
  187.       ;
  188.    }
  189.  
  190.  
  191. #if NeedFunctionPrototypes
  192. static void s3_init_clock(unsigned long setup, unsigned short crtcport)
  193. #else
  194. static void s3_init_clock(setup, crtcport)
  195.    unsigned long setup;
  196.    unsigned short crtcport;
  197. #endif
  198.    {
  199.    unsigned char nclk[2], clk[2];
  200.    unsigned short restore42;
  201.    unsigned short oldclk;
  202.    unsigned short bitval;
  203.    int i;
  204.    unsigned char c;
  205.  
  206.    (void)xf86DisableInterrupts();
  207.  
  208.    oldclk = inb(0x3CC);
  209.  
  210.    outb(crtcport, 0x42);
  211.    restore42 = inb(crtcport+1);
  212.  
  213.    outw(0x3C4, 0x0100);
  214.  
  215.    outb(0x3C4, 1);
  216.    c = inb(0x3C5);
  217.    outb(0x3C5, 0x20 | c);
  218.  
  219.    outb(crtcport, 0x42);
  220.    outb(crtcport+1, 0x03);
  221.  
  222.    outw(0x3C4, 0x0300);
  223.  
  224.    nclk[0] = oldclk & 0xF3;
  225.    nclk[1] = nclk[0] | 0x08;
  226.    clk[0] = nclk[0] | 0x04;
  227.    clk[1] = nclk[0] | 0x0C;
  228.  
  229.    outb(crtcport, 0x42);
  230.    i = inw(crtcport);
  231.  
  232.    outw(0x3C4, 0x0100);
  233.  
  234.    wrt_clk_bit(oldclk | 0x08);
  235.    wrt_clk_bit(oldclk | 0x0C);
  236.    for (i=0; i<5; i++) {
  237.       wrt_clk_bit(nclk[1]);
  238.       wrt_clk_bit(clk[1]);
  239.       }
  240.    wrt_clk_bit(nclk[1]);
  241.    wrt_clk_bit(nclk[0]);
  242.    wrt_clk_bit(clk[0]);
  243.    wrt_clk_bit(nclk[0]);
  244.    wrt_clk_bit(clk[0]);
  245.    for (i=0; i<24; i++) {
  246.       bitval = setup & 0x01;
  247.       setup >>= 1;
  248.       wrt_clk_bit(clk[1-bitval]);
  249.       wrt_clk_bit(nclk[1-bitval]);
  250.       wrt_clk_bit(nclk[bitval]);
  251.       wrt_clk_bit(clk[bitval]);
  252.       }
  253.    wrt_clk_bit(clk[1]);
  254.    wrt_clk_bit(nclk[1]);
  255.    wrt_clk_bit(clk[1]);
  256.  
  257.    outb(0x3C4, 1);
  258.    c = inb(0x3C5);
  259.    outb(0x3C5, 0xDF & c);
  260.  
  261.    outb(crtcport, 0x42);
  262.    outb(crtcport+1, restore42);
  263.  
  264.    outb(0x3C2, oldclk);
  265.  
  266.    outw(0x3C4, 0x0300);
  267.  
  268.    xf86EnableInterrupts();
  269.  
  270.    }
  271.  
  272. static void wrt_clk_bit(value)
  273.    unsigned int value;
  274.    {
  275.    int j;
  276.  
  277.    outb(0x3C2, value);
  278.    for (j=2; --j; )
  279.       inb(0x200);
  280.    }
  281.  
  282.  
  283. /*
  284.  *  ET4000 ICD2061 (Diamond Stealth 32) clock setting code.
  285.  *    Original by Frank Klemm
  286.  *    Linux port by Ray Balister.
  287.  *    various improvements by Peter Chang
  288.  *    included in XFREE code base by Koen Gadeyne
  289.  */
  290.  
  291. static void et4000_init_clock(unsigned long setup)
  292. {
  293.     register unsigned char a=inb(0x3CC) & ~0x0C;
  294.     register unsigned i;
  295.     unsigned long m;
  296.  
  297. #define S(x)    outb(0x3C2,a | 4*(x))
  298.  
  299.     for (i=0; i<5; i++)
  300.       S(2), S(3);
  301.     for (i=0; i<2; i++)
  302.       S(0), S(1);
  303.     for (i=0, m=1; i<24; i++, m+=m)
  304.       if (setup & m)
  305.     S(1), S(0), S(2), S(3);
  306.       else
  307.     S(3), S(2), S(0), S(1);
  308.     S(3), S(2), S(3);
  309.     S(3);
  310.  
  311. #undef S
  312.  
  313. }
  314.